package com.kinth.work.webmagic.huicong;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.Scanner;
/**
 * 
 * <p>
 * Title: 慧聪网企业数据抓取
 * </p>
 * <p>
 * 用户参考：
 * 
 * 1. 目前的程序，只需要运行Main类即可。程序会边存边取，程序结束的标识是控制台不断重复输出
 *    GetInfo: 当下公司链接已经爬取完毕。请结合其他列表情况判断是否已经完成
 *    RealCompanyUrl: 当下公司列表链接已经爬取完毕。请结合其他列表情况判断是否已经完成
 *    GetBigUrl2: 当下分类列表已经爬取完毕。已经爬取完毕。如果公司列表和公司都爬取完毕。请关闭程序。
 *    这三句话。
 * 2. 由于为了预防程序中断，程序会在项目根目录下面生成三个文件，分别记录的是当前程序运行的位置。中断后直接启动即可。所以
 *    转移项目时请把这三个文件一并转移。
 * 3. 控制台输出的“重复插入”是表示重复插入，不用在意。如果报错：Communications link failure，这也不需要在意。
 *    mysql的问题。不影响运行。
 * </p>
 * <p>
 * 开发者指南：
 * 
 * Description: 这个类是Main函数所在类。直接运行即可。 1.
 * 首先是http://info.b2b.hc360.com/list/company.shtml,这是总的起始页。而GetBigUrl是处理这一页的。
 * 用来得到下一页的链接。这里有个问题，就是此页得到的链接是不能用的。也就是直接利用links()函数得到的链接是不能用
 * 的。如果用这个链接，在地址栏会自动改变地址。我也不知道为什么。为了解决这个问题，需要自己解析拼接地址。经过观察，
 * （也就是2里面的地址),你可以发现，只需要把w=破译掉即可。而它正式这个链接的text()的中文的Url编码。所以，直接 自己提取出来自己组合即可。 2.
 * http://s.hc360.com/?w=%CE%E5%BD%F0&mychannel=enterprise，这是跳转到的页面。为了处理分页，需要
 * 先把总的页数提取出来。而GetBigUrl2是处理这个问题的。他会根据1中的链接，逐个打开并提取分页数目。这里分页数目需要
 * 注意，根据网站的js代码。分页数目最大是100.也许根据总的条目数是超过一百页的。但是这个网站设置了只能到100.所以我们 也只能取到一百页。 3.
 * http://s.hc360.com/?w=%CE%E5%BD%F0&mychannel=enterprise，还是这个页面，不过这次是为了提取具体
 * 公司的链接。RealCompanyUrl是用来处理这个问题的。这个问题比较简单。直接提取出来即可。 4.
 * http://cfqj.b2b.hc360.com/，这是具体的公司页面。（暂时没有发现其他类型的页面）。提取相关item.目前提取了
 * 公司名称，产品，地址，qq,联系方式，公司简介。微信是提取不出来的。因为它是直接跳出一个界面。 5. 由于程序太大。还没有系统测试过。单元测试完成。
 * 
 * ******************************************************************************
 * 这是第2版的注释：version 2.0 1. 完成了与数据库的对接。 2. 完成了提取联系方式 3. 完成了提取分类信息。 4.
 * 完成了单元测试，但是没有系统测试
 * *******************************************************************************
 * 这算是第三版的注释： 1. 上面的程序有个很大的问题，就是所有的东西都存在了内存里面。所以这一次在GetBigUrl2里面先把所有的列表页的
 * 网址读入一个文件（bigurl.txt）。然后在RealCompanyUrl里面在把列表页都读出来，然后把所有提取到的公司
 * 地址在保存到一个文件（companyurl.txt）。然后GetInfo里面再读出来，一个一个的抓取。 2.
 * 这里首先，GetBigUrl和RealCompanyUrl调用都是在GetInfo里面完成的。由于每个类共用一个文件，也就是在每
 * 类里面文件都是static，而且RealCompanyUrl要使用文件必须等到GetBigUrl先写入。这样就防止了读写混乱。
 * 但是没能实现边读边写。这是不太好的一点。 4. 为了每个类里面不同线程写入时不发生混乱，给每个write操作加了锁。这样，就不会互相干扰了。 5.
 * 边读边写还没有想好怎么实现。这应该是下一步的目标。实现方法目前觉得还是用一个文件，只是读取的时候分批量读取， 这样会好一点。
 * 
 * ***************************************************************************************
 * 这是第四版注释：3月28号更新
 * 1. 完成了边存边取。因为上面第三步前面抓取公司的链接时间太久，运行几天还没有开始抓公司的数据。原来以为之所以几个爬虫串行应该是文件的问题，现在，貌似是线程
 * 池之间都是串行。只有线程池内的线程才是并行。然后就想到根据线程数目来控制进度。因为主要的问题就是自己无法判断一个线程是否已经进行完毕。比如先开一个线程
 * 读取一个类别，然后串行运行到后面。但是无法判断运行到后面是不是线程已经完成，也就无法自动开始一个新的。自己试了很多方法，但是依旧无法得到线程数目。得到的
 * 在Main函数里面始终是1.现在觉得，也许线程池的话是不一样的。这个需要探究一下。后来又想到也许可以调用webmagci的接口来查看线程。虽然有这么一个接口。
 * 但是返回值依旧是1.所以也失败了。
 * 2. 后来由于文件的并发问题，加上旋哥的指导，想到用数据库代替文件，这样就把并发读取的问题交给数据库。自己就可以边存边去了。于是就实现了。但是还是无法并行。
 * 于是采用线程，每个类自己实现Runnable接口，解决了这个问题。现在是可以了。
 * 3. 每个线程如果目前列表没有数据，就会睡眠并不断循环。
 * 4. 如果程序中间中断，程序也会吧目前读取到哪里写入文件，下次启动不会从头开始。只有一开始的大类会每次从头开始。但是，这个比较小，只有832个连接。所以不必
 * 在意，用不了多少时间。
 * 现在的程序架构发生了一点变化：
 * 1. com.kinth.dbutil这个包是用来连接数据库的。主要是jdbc5连接服务器的mysql。
 * 2. FileUtil表示文件的读取工具类。主要是三个文件的读取。就是记录程序运行到哪里。
 * 3. UrlHuiCong是一个bean，主要用于程序运行期间对数据库的操作。
 * 4. dbUtil表示为慧聪网抓取量身定做的数据库操作类，主要和com.kinth.dbutil里面进行交互。
 * 5. Main类主要是调用GetInfo,RealCompanyUrl, GetBigUrl2,GetBigUrl.
 * 6. mysql数据库里面主要新增了三张表，就是huicong_url1, huicong_url2,huicong_url3。储存程序运行中存储的
 *    url.
 * 7. 最终数据存储在mail_info表中。
 * ************************************************************************************
 * 第五版：主要解决很多没有qq的问题，因为联系方式里面也有qq，所以进行两次提取。但是因为下面的qq是动态加载的。所以需要
 * 用到浏览器渲染，这里用的是phantomjs。主要封装在JSUtil里面。传入url，然后可以得到qq附近的html。
 * 1. 重点是如何运行。这里有了一个硬性要求，就是必须在项目更目录下面安装phantomjs。实际就是直接解压。但是必须保证
 *    路径和JSUtil里面的exePath保持一致。文件名等都需要一致。如果是linux版本。请先安装phantomjs的linux版本。
 *    
 * 2. 因为抓取到的动态加载qq都是重复的，所以暂时注释掉phantomJS的调用。注释主要在GetInfo类里面。有两处。
 * </p>
 * 
 * @author kaikai
 * @2017年3月21日
 */
public class Main
{

	public static void main(String[] args) throws InterruptedException
	{
		//先在两个记录文件里面填入0
		FileUtil fileUtil = new FileUtil();
        //此处文件是不会被覆写的。
		//System.out.println(FileUtil.getBigUrl());
		GetInfo getInfo = new GetInfo();
		Thread t1 = new Thread(getInfo);
		t1.start();
		
		System.out.print("Main: GetInfo启动。");
		RealCompanyUrl realCompanyUrl = new RealCompanyUrl();
		Thread t2 = new Thread(realCompanyUrl);
		t2.start();
		
		System.out.print("Main: RealCompanyUrl启动。");
		GetBigUrl2 getBigUrl2 = new GetBigUrl2();
		Thread t3 = new Thread(getBigUrl2);
		t3.start();

    	System.out.print("Main: bigUrl2运行完毕。");

        GetBigUrl getBigUrl = new GetBigUrl();
        Thread t4 = new Thread(getBigUrl);
        t4.start();
        System.out.print("Main: bigUrl运行完毕。");

	}

}
